<?php

namespace Biz\service\Store;

use Biz\model\store\MStoreContent;
use Biz\service\wiki\ObjRelateWiki;
use Doraemon\amqp\CommunityQueue;
use Doraemon\cache\Queue;
use Doraemon\model\AdmReportRelateEvaluation;
use Doraemon\model\Blank as DbBlank;
use Doraemon\model\MyArticleList;
use Doraemon\model\Photos as mPhotos;
use Doraemon\module\ReleaseService\Note\Base\Diary\EditDiaryStatusToDelete;
use Doraemon\module\ReleaseService\Note\Base\Photo\EditPhotoStatusToDelete;
use Doraemon\module\ReleaseService\Note\Base\Topic\EditTopicStatusToDelete;
use Doraemon\service\Article;
use Doraemon\service\Content\AdmContent;
use Doraemon\service\MainTag;
use Doraemon\service\Photos as sPhotos;
use Doraemon\service\statSign\Basic;
use Doraemon\tools\ActionLog;
use Doraemon\tools\BlockType;
use Doraemon\tools\HhzClient;
use Doraemon\tools\IdParse;
use Doraemon\tools\Log;
use Doraemon\tools\PointConfig;
use Exception;

class StoreContent
{
    private static $instance = null;
    private $id = 0; //门店内容id
    private $storeId = 0; //门店id
    private $esIds = []; //es结果
    private $debug = false; //日志开关
    public static $delContentStatus = [
        MStoreContent::CONTENT_STATUS_DELETE,
        MStoreContent::CONTENT_STATUS_USER_DELETE
    ];

    private static $contentStatus = [
        0 => '全部',
        1 => '已收录',
        2 => '已置顶',
        3 => '取消收录',
    ];

    private static $contentType = MStoreContent::CONTENT_TYPE_MAP;

    public function __construct($storeId = 0, $id = 0)
    {
        $this->storeId = $storeId;
        $this->id = $id;
    }

    /**
     * @param mixed $params
     * @return self
     */
    public static function getInstance(...$params)
    {
        if (self::$instance) return self::$instance;

        return new self(...$params);
    }

    /**
     * app接口 获取门店排除的动态
     */
    public static function delContentList($storeId)
    {
        $where = [
            'store_id' => $storeId,
            'content_status' => MStoreContent::CONTENT_STATUS_DELETE,
            'content_module' => MStoreContent::CONTENT_MODULE_STORE,
        ];
        return MStoreContent::select('obj_id', $where);
    }

    /**
     * app接口 内容管理的门店
     */
    public static function objRelateStore($objId)
    {
        $response = [];
        if (!empty($objId)) {
            if (is_scalar($objId)) $objId = [$objId];

            $rs = MStoreContent::select(['obj_id', 'store_id', 'create_from'], ['obj_id' => $objId, 'content_status' => [MStoreContent::CONTENT_STATUS_SUCCESS, MStoreContent::CONTENT_STATUS_CANCEL]]);
            $objMap = [];
            if ($rs) {
                foreach ($rs as $v) {
                    if ($v['create_from'] & MStoreContent::CONTENT_FROM_TAG) {
                        $storeIds[] = $v['store_id'];
                        $objMap[$v['obj_id']][] = $v['store_id'];
                    }
                }
            }
            $store = empty($storeIds) ? [] : \Biz\service\Store\StoreBasicService::getMilitiStoreList($storeIds);
            $storeMap = empty($store) ? [] : array_column($store, null, 'id');
            foreach ($objMap as $id => $storeIdArr) {
                $temp = [];
                foreach ($storeIdArr as $v) {
                    if (isset($storeMap[$v])) $temp[] = $storeMap[$v];
                }
                $response[$id] = [
                    'list' => $temp,
                ];
            }
        }
        return $response;
    }

    public function esList($esCondition, $filter = false)
    {
        $rs = SearchSchedule::search(new \Biz\module\Classes\adm\StoreContentSearch($esCondition));
        $is_over = $rs['is_over'] ?? 1;
        $total = $rs['total'] ?? 0;
        $ids = $rs['list'] ?? [];


        $this->esIds = $ids;
        $condition = ['id' => $ids];
        if ($filter && !in_array(HhzClient::getClientType(), [HhzClient::APPTYPE_H5, HhzClient::APPTYPE_IOS, HhzClient::APPTYPE_ANDROID,])) {
//            $condition['content_type[!]'] = MStoreContent::CONTENT_TYPE_VIDEO;
        }


        $rs = $ids ? MStoreContent::select('*', $condition) : [];
        $rsMap = empty($rs) ? [] : array_column($rs, null, 'id');
        $list = [];
        foreach ($ids as $id) {
            if (isset($rsMap[$id])) $list[] = $rsMap[$id];
        }
        return compact('is_over', 'total', 'list');
    }

    /**
     * app接口 住友说
     * @param     $uid  int 用户id
     * @param int $module
     * @param     $page int 页码
     * @param int $size
     * @return array
     */
    public function hhzPagedList($uid, $module = MStoreContent::CONTENT_MODULE_USER, $page = 1, $size = 20, $sort = 0, $from = 'store_home')
    {
        $esSort = $sort > 0 ? 'platform' : 'default';
        if ($es = true) {
            $esCondition = [
                'sort' => $esSort,
                'page' => $page,
                'per_page' => $size,
                'store_id' => $this->storeId,
                'content_module' => $module,
                'content_status' => MStoreContent::CONTENT_STATUS_SUCCESS,
            ];
            $esRs = $this->esList($esCondition, false);
            $is_over = $esRs['is_over'] ?? 1;
            $total = $esRs['total'] ?? 0;
            $rs = $esRs['list'] ?? [];
        } else {
            $offset = $page < 1 ? 0 : ($page - 1) * $size;
            $condition = [
                'content_status' => MStoreContent::CONTENT_STATUS_SUCCESS,
                'store_id' => $this->storeId,
                'content_module' => $module,
            ];

            $limitCondition = [
                'LIMIT' => [
                    $offset, $size
                ],
            ];

            $orderCondition = [
                'ORDER' => [
                    'top_time' => 'DESC',
                    'created_at' => 'DESC',
                ],
            ];

            $rs = MStoreContent::select('*', $condition + $limitCondition + $orderCondition);
            $total = MStoreContent::count($condition);
            $is_over = $total > $page * $size ? 0 : 1;
        }

        //格式化数据
        $objBase = [];
        foreach ($rs as $v) {
            $objBase[] = [
                'obj_id' => $v['obj_id'],
                'obj_type' => $v['obj_type']
            ];
        }

        $map = \Doraemon\service\Format\FormatMix::format($objBase, $uid, \Doraemon\pockets\constInterface\FormatScene::STORE);
        $c = count($map);
        Log::position_info('门店列表数据', compact('module', 'from', 'page', 'is_over', 'sort', 'esSort', 'rs', 'c') + ['esIds' => $this->esIds]);
        $list = [];
        foreach ($rs as $v) {
            $obj_type = $v['obj_type'];
            $obj_id = $v['obj_id'];
            if (isset($map[$obj_type][$obj_id])) {
                $temp = $map[$obj_type][$obj_id];
                $tempModule = $module == MStoreContent::CONTENT_MODULE_USER ? Basic::MODULE_STORE_HOME_CARD_LIST : Basic::MODULE_STORE_HOME_DESIGNER_CARD_LIST;
                $temp['statSign'] = Basic::genStatSign($tempModule, [
                    Basic::EXTEND_KEY_FROM => $from,
                    Basic::EXTEND_KEY_OBJ_TYPE => $obj_type,
                    Basic::EXTEND_KEY_OBJ_ID => $obj_id,
                ], ['store_id' => $this->storeId]);
                //主页去掉门店卡片和wiki卡片
//                if ($from == 'store_home') {
                if (!empty($temp['photo']['wiki_info']['list'])) $temp['photo']['wiki_info']['list'] = [];
                if (!empty($temp['photo']['store_info']['list'])) $temp['photo']['store_info']['list'] = [];
                if (!empty($temp['blank']['wiki_info']['list'])) $temp['blank']['wiki_info']['list'] = [];
//                }
                $list[] = $temp;
            }
        }

        return compact('list', 'is_over', 'total');
    }

    /**
     * 获取关联记录
     *
     * @throws Exception
     */
    private function getOneWithCheck()
    {
        $id = $this->id;
        $storeId = $this->storeId;

        $info = MStoreContent::get('*', ['id' => $id]);

        if (empty($info)) throw new Exception('记录不存在');

        if ($info['store_id'] != $storeId) throw new Exception('无权操作');

        return $info;
    }

    private function changeContentStatus($info, $contentStatus): bool
    {
        if ($info['content_status'] == $contentStatus) return true;

        $data = [
            'top_time' => 0,
            'content_status' => $contentStatus,
            'updated_at' => date("Y-m-d H:i:s"),
        ];

        $where = ['id' => $this->id];

        $result = MStoreContent::update($data, $where)->rowCount() > 0;

        if ($result) {
            // 更新住友说,设计师说的数量
            if ($info['content_module'] == MStoreContent::CONTENT_MODULE_DESIGNER) $msgType = \Doraemon\cache\UserCounter::TYPE_DESIGNER_SAID;
            if ($info['content_module'] == MStoreContent::CONTENT_MODULE_USER) $msgType = \Doraemon\cache\UserCounter::TYPE_LIVER_SAID;
            if (isset($msgType)) {
                $uid = StoreBasicService::getStoreUidById($info['store_id']);
                if ($contentStatus == MStoreContent::CONTENT_STATUS_SUCCESS) {
                    \Doraemon\cache\UserCounter::increaseUserCounter($uid, $msgType);
                } else {
                    \Doraemon\cache\UserCounter::decreaseUserCounter($uid, $msgType);
                }
                StoreContentSync::getCounter($info['obj_id'], true);
            }
        }

        return $result;
    }

    /**
     * 取消置顶
     * @throws Exception
     */
    public function cancelTop(): bool
    {
        $info = $this->getOneWithCheck();

        if ($info['content_module'] == MStoreContent::CONTENT_MODULE_STORE) throw new Exception('不允许此操作');

        if ($info['top_time'] == 0) return true;

        $data = [
            'top_time' => 0,
            'updated_at' => date("Y-m-d H:i:s"),
        ];
        $where = ['id' => $this->id];

        return MStoreContent::update($data, $where)->rowCount() > 0;
    }

    /**
     * 置顶
     * @throws Exception
     */
    public function top(): bool
    {
        $info = $this->getOneWithCheck();

        if ($info['content_module'] == MStoreContent::CONTENT_MODULE_STORE) throw new Exception('不允许此操作');

        if ($info['top_time'] > 0) return true;

        if (MStoreContent::count(['store_id' => $info['store_id'], 'content_status' => MStoreContent::CONTENT_STATUS_SUCCESS, 'content_module' => $info['content_module'], 'top_time[>]' => 0]) >= 3) throw new Exception('最多能置顶3条住友内容');

        $data = [
            'top_time' => time(),
            'updated_at' => date("Y-m-d H:i:s"),
        ];
        $where = ['id' => $this->id];

        return MStoreContent::update($data, $where)->rowCount() > 0;
    }

    /**
     * 重新收录
     * @throws Exception
     */
    public function delete(): bool
    {
        $info = $this->getOneWithCheck();

        if ($info['content_module'] != MStoreContent::CONTENT_MODULE_STORE) throw new Exception('不允许此操作');

        $response = $this->changeContentStatus($info, MStoreContent::CONTENT_STATUS_DELETE);

        if ($info['content_status'] == MStoreContent::CONTENT_STATUS_DELETE) return $response;

        $objType = $info['obj_type'];
        $objId = $info['obj_id'];
        try {
            switch ($objType) {
                case BlockType::TYPE_PHOTO:

                    $photoInfo = sPhotos::getPhoto($objId);
                    $photoInfo['note_id'] = $photoInfo['id'];
                    if ($photoInfo['topic_activity_id']) {
                        (new EditTopicStatusToDelete($photoInfo))->edit();
                    } else if ($photoInfo['type'] == mPhotos::TYPE_DIARY) {
                        (new EditDiaryStatusToDelete($photoInfo))->edit();
                    } else {
                        (new EditPhotoStatusToDelete($photoInfo))->edit();
                    }
                    break;
                case BlockType::TYPE_BLANK:
                    // 判断内容是否存在
                    $blank_data = DbBlank::getBlank($objId);
                    if (empty($blank_data) || !is_array($blank_data)) throw new \Exception("内容不存在");
                    // 删除合并表数据
                    MyArticleList::delByObjId($objId);
                    // 删除内容
                    $result = DbBlank::delBlank($objId);
                    //删除主标签redis里的内容
                    if ($blank_data['main_tag']) MainTag::handleEditMainTag($blank_data['main_tag'], $blank_data['bid']);

                    // 返回结果
                    if ($result) {
                        $uid = $blank_data['uid'];
                        //投日志
                        ActionLog::log($uid, ['device_type' => 'pc', 'blank_id' => $objId], ActionLog::DELETE_BLANK);
                        \Doraemon\tools\Sensors::track($uid, ['device_type' => 'pc', 'blank_id' => $objId], ActionLog::DELETE_BLANK);

                        \Doraemon\model\Comment::delCommentByObjId($objId);
                        CommunityQueue::insertQueue('/queue/Es/deleteByObjId', [
                            'obj_id' => $objId,
                        ], CommunityQueue::QUEUE_COMMUNITY);
                        Queue::insertQueue('Blank/deleteBlank', ['blank_id' => $objId]);
                        Queue::insertQueue('BodyClean/roomService', ["type" => "blank", 'obj_id' => $objId]);

                        // 更新测评文章状态为删除状态
//                        Queue::insertQueue('Evaluation/deleteBlank', ['blank_id' => $objId]);
                        AdmReportRelateEvaluation::updateByObjId($objId, ["status" => AdmReportRelateEvaluation::STATUS_DELETE]);
                        ObjRelateWiki::delBlankRelate($uid, $objId);

                        //级别为「编辑推荐」的文章（包括空白和整屋）被用户删除, 下发微信通知相关同事
                        if ($blank_data['admin_score'] >= 80) {
                            \Doraemon\service\Frequency::delBlank($uid, $blank_data['title']);
                        }

                        Queue::insertQueue('TotalArticle/delArticleById', ['article_id' => $objId]);
                    }
                    break;
            }
        } catch (\Exception $e) {
            Log::position_info("门店删除debug", ['objId' => $objId, 'message' => $e->getMessage()]);
        }

        return $response;
    }

    /**
     * 重新收录
     * @throws Exception
     */
    public function reclaim(): bool
    {
        $info = $this->getOneWithCheck();

        if ($info['content_module'] == MStoreContent::CONTENT_MODULE_STORE) throw new Exception('[我的发布]不允许此操作');

        return $this->changeContentStatus($info, MStoreContent::CONTENT_STATUS_SUCCESS);
    }

    /**
     * 取消收录
     * @throws Exception
     */
    public function cancel(): bool
    {
        $info = $this->getOneWithCheck();

        if ($info['content_module'] == MStoreContent::CONTENT_MODULE_STORE) throw new Exception('[我的发布]不允许此操作');

        return $this->changeContentStatus($info, MStoreContent::CONTENT_STATUS_CANCEL);
    }

    /**
     * 商家内容管理列表
     *
     */
    public function mangePagedList($page = 1, $searchCondition = [], $size = 20)
    {
        $offset = $page < 1 ? 0 : ($page - 1) * $size;
        $condition = [
            'content_status[!]' => [MStoreContent::CONTENT_STATUS_USER_DELETE, MStoreContent::CONTENT_STATUS_DELETE],
            'store_id' => $this->storeId,
        ];
        $can_top = MStoreContent::count(['store_id' => $this->storeId, 'top_time[>]' => 0, 'content_module' => $searchCondition['module']]) >= 3;
        //切换成es搜索条件
        if ($es = true) {
            $esCondition = [
                'page' => $page,
                'per_page' => $size,
                'store_id' => $this->storeId,
                'content_status' => [MStoreContent::CONTENT_STATUS_SUCCESS, MStoreContent::CONTENT_STATUS_CANCEL],
            ];
            if ($searchCondition['module']) $esCondition['content_module'] = $searchCondition['module'];
            if (strlen($searchCondition['keyword'])) $esCondition['keyword'] = $searchCondition['keyword'];
            if ($searchCondition['contentType']) $esCondition['content_type'] = $searchCondition['contentType'];
            if ($searchCondition['contentStatus']) {
                if ($searchCondition['contentStatus'] == 1) {
                    $esCondition['content_status'] = MStoreContent::CONTENT_STATUS_SUCCESS;
                } elseif ($searchCondition['contentStatus'] == 2) {
                    $esCondition['is_top'] = 1;
                } else {
                    $esCondition['content_status'] = MStoreContent::CONTENT_STATUS_CANCEL;
                }
            }
            if ($searchCondition['publishDateStart']) $esCondition['created_time_range']['start'] = $searchCondition['publishDateStart'];
            if ($searchCondition['publishDateEnd']) $esCondition['created_time_range']['end'] = $searchCondition['publishDateEnd'];

            $esRs = $this->esList($esCondition);
            $is_over = $esRs['is_over'] ?? 1;
            $total = $esRs['total'] ?? 0;
            $rs = $esRs['list'] ?? [];
        } else {
            //条件处理
            if ($searchCondition['module']) $condition['content_module'] = $searchCondition['module'];
            if (strlen($searchCondition['keyword'])) $condition['words[~]'] = $searchCondition['keyword'];
            if ($searchCondition['contentType']) $condition['content_type'] = $searchCondition['contentType'];
            if ($searchCondition['contentStatus']) {

//        1 => '已收录',
//        2 => '已置顶',
//        3 => '取消收录',
                if ($searchCondition['contentStatus'] == 1) {
                    unset($condition['content_status[!]']);
                    $condition['content_status'] = MStoreContent::CONTENT_STATUS_SUCCESS;
                } elseif ($searchCondition['contentStatus'] == 2) {
                    $condition['top_time[>]'] = 0;
                } else {
                    unset($condition['content_status[!]']);
                    $condition['content_status'] = MStoreContent::CONTENT_STATUS_CANCEL;
                }
            }
            if (strlen($searchCondition['publishDateStart'])) $condition['created_at[>=]'] = date("Y-m-d 00:00:00", strtotime($searchCondition['publishDateStart']));
            if (strlen($searchCondition['publishDateEnd'])) $condition['created_at[<=]'] = date("Y-m-d 23:59:59", strtotime($searchCondition['publishDateEnd']));

            $limitCondition = [
                'LIMIT' => [
                    $offset, $size
                ],
                'ORDER' => [
                    'top_time' => 'DESC',
                    'created_at' => 'DESC'
                ],
            ];
            $rs = MStoreContent::select('*', $condition + $limitCondition);
            Log::position_info('门店列表', ['sql' => MStoreContent::log()]);
            $total = MStoreContent::count($condition);
            $is_over = $total > $page * $size ? 0 : 1;
        }

        $list = [];
        foreach ($rs as $v) {
            $obj_type = $v['obj_type'];
            $obj_id = $v['obj_id'];
            $info = AdmContent::get($obj_type, $obj_id);
            $info = $info[$obj_id] ?? [];
            $topped = $v['top_time'] > 0;
            $list[] = [
                'id' => $v['id'],
                'obj_id' => $obj_id,
                'obj_type' => $obj_type,
                'title' => $info['title'] ?? '',
                'content' => $info['content'] ?? '',
                'cover_pic_url' => $info['cover_pic_url'] ?? '',
                'type_desc' => $info['type_desc'] ?? '',
                'addtime' => date("Y.m.d", $info['addtime']),
                'content_status_desc' => $topped && $v['content_status'] == MStoreContent::CONTENT_STATUS_SUCCESS ? '已顶置' : MStoreContent::CONTENT_STATUS_MAP[$v['content_status']],
                'content_status' => $v['content_status'],
//                //1 精选 0 普通 2 当天禁用设置精选
//                'can_selected' => $alreadySelected ? 2 : ($v['is_selected'] == 1 ? 0 : $can_selected),
                //1 可以置顶 0不支持置顶
                'can_top' => $can_top,
                'topped' => $topped ? 1 : 0,//1:置顶 0：未置顶
                'link' => \Biz\service\wiki\WikiContent::getAppLink($obj_id)
            ];
        }

        return compact('list', 'total', 'is_over');
    }

    public function manageContentStatus($module = MStoreContent::CONTENT_MODULE_USER): array
    {
        $options = self::$contentStatus;

        if ($module == MStoreContent::CONTENT_MODULE_STORE) $options = ['全部'];

        return $this->formatOptions($options);
    }

    public function manageContentType($module = MStoreContent::CONTENT_MODULE_USER): array
    {
        $options = self::$contentType;

        return $this->formatOptions($options);
    }

    public function formatOptions($options = []): array
    {
        $response = [];
        if (!is_array($options) || empty($options)) return $response;

        foreach ($options as $key => $v) {
            $response[] = [
                'id' => $key,
                'title' => $v,
            ];
        }
        return $response;
    }

    public static function getRelStoreIdsByObjId($obj_id): array
    {
        $obj_ids = is_scalar($obj_id) ? [$obj_id] : $obj_id;

        $aIds = [];
        $queryObjIds = [];
        foreach ($obj_ids as $v) {
            if (IdParse::getType($v) == BlockType::TYPE_ARTICLE) {
                $noteIds = Article::getRelaNoteIds($v);
                if ($noteIds) $aIds[$v] = $noteIds;
                $queryObjIds = array_merge($queryObjIds, $noteIds);

            } else {
                $queryObjIds[] = $v;
            }
        }

        $list = empty($queryObjIds) ? [] : MStoreContent::select(['store_id', 'obj_id', 'create_from'], ['obj_id' => $queryObjIds, 'content_status' => [MStoreContent::CONTENT_STATUS_SUCCESS, MStoreContent::CONTENT_STATUS_CANCEL]]);
        $map = [];
        foreach ($list as $v) {
            if ($v['create_from'] & MStoreContent::CONTENT_FROM_TAG) {
                $map[$v['obj_id']][$v['store_id']] = $v['store_id'];
            }
        }
        $map = empty($map) ? [] : array_map(function ($v) {
            return array_values($v);
        }, $map);

        $response = [];
        foreach ($obj_ids as $v) {
            $objType = IdParse::getType($v);
            if ($objType == BlockType::TYPE_ARTICLE) {
                $noteIds = $aIds[$v] ?? [];
                $temp = [];
                foreach ($noteIds as $i) {
                    $temp = array_merge($temp, $map[$i] ?? []);
                }
                $temp = array_flip(array_flip($temp));
            } else {
                $temp = $map[$v] ?? [];
            }
            $response[$objType][$v] = $temp;
        }

        return $response;
    }

}